package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.DesignBase;
import com.ruoyi.system.domain.DesignScheme;
import com.ruoyi.system.domain.PmMaterialList;
import com.ruoyi.system.dto.*;
import com.ruoyi.system.entity.*;
import com.ruoyi.system.enums.*;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.*;
import com.ruoyi.system.vo.*;
import com.ruoyi.system.service.msg.MsgDetailEnricher;
import com.ruoyi.system.service.msg.H5MsgConfirmHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service
public class MsgPushServiceImpl extends ServiceImpl<MsgPushTaskMapper, MsgPushTaskDO> implements MsgPushService {

    @Resource
    private MsgTemplateService templateService;

    @Resource
    private MshPushTaskItemService mshPushTaskItemService;

    @Resource
    private MsgActionLogMapper logMapper;

    @Resource
    private List<MsgDetailEnricher> msgDetailEnrichers;

    @Resource
    private List<H5MsgConfirmHandler> msgConfirmHandlers;

    @Resource
    private DesignBaseService designBaseService;

    @Resource
    private DesignSchemeService designSchemeService;

    @Resource
    private IConstructionItemService projectItemService;

    @Resource
    private ConstructionProjectService constructionProjectService;

    @Resource
    private ContractService contractService;

    @Resource
    private IPmMaterialListService pmMaterialListService;

    @Resource
    private IDemandChangeRequestService demandChangeRequestService;

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveDraft(UnifiedPushDTO pushDTO) {
        // 模板校验
        MsgTemplateDO template = templateService.getById(pushDTO.getTemplateId());
        if (template == null || Objects.equals(template.getStatus(), 0)) {
            throw new ServiceException("模板不可用");
        }

        // 新建草稿，转换为创建DTO并调用创建方法
        if (pushDTO.getId() != null) {
            updateTask(pushDTO, template);
        } else {
            createTask(pushDTO, template);
        }
        return true;
    }

    private void updateTask(UnifiedPushDTO pushDTO, MsgTemplateDO template) {
        MsgPushTaskDO task = this.lambdaQuery()
                .eq(MsgPushTaskDO::getId, pushDTO.getId())
                .eq(MsgPushTaskDO::getIsDeleted, 0)
                .one();
        if (task == null) {
            throw new ServiceException("草稿不存在或不可编辑");
        }

        task.setTemplateId(pushDTO.getTemplateId());
        task.setProjectId(pushDTO.getProjectId());
        task.setProjectName(pushDTO.getProjectName());
        task.setBusinessId(pushDTO.getBusinessId());
        task.setRemark(pushDTO.getRemark());

        JSONObject contentVarsJson = new JSONObject();
        contentVarsJson.put("projectName", pushDTO.getProjectName());
        task.setContentVars(contentVarsJson.toJSONString());
        task.setUpdateTime(LocalDateTime.now());

        processTemplateAndRender(task, template);

        MsgPushTaskItemDO msgPushTaskItemDO = mshPushTaskItemService.lambdaQuery()
                .eq(MsgPushTaskItemDO::getTaskId, task.getId())
                .eq(MsgPushTaskItemDO::getIsDeleted, 0)
                .eq(MsgPushTaskItemDO::getProcessStatus, MsgProcessStatusEnum.PENDING.getCode()).one();

        Integer signStatus = (template.getNeedSignature() == 0) ? 0 : 1;

        if (msgPushTaskItemDO != null) {
            msgPushTaskItemDO.setReceiverId(pushDTO.getH5UserId());
            msgPushTaskItemDO.setReceiverName(pushDTO.getH5UserName());
            msgPushTaskItemDO.setSignStatus(signStatus);
        } else {
            MsgPushTaskItemDO newItem = new MsgPushTaskItemDO();
            newItem.setTaskId(task.getId());
            newItem.setReceiverId(pushDTO.getH5UserId());
            newItem.setReceiverName(pushDTO.getH5UserName());
            newItem.setProcessStatus(MsgProcessStatusEnum.PENDING.getCode());
            newItem.setCreateTime(LocalDateTime.now());
            newItem.setSignStatus(signStatus);
            msgPushTaskItemDO = newItem;
        }
        mshPushTaskItemService.saveOrUpdate(msgPushTaskItemDO);
        this.updateById(task);

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean sendNow(Long taskId, String operator) {
        MsgPushTaskDO task = this.lambdaQuery()
                .eq(MsgPushTaskDO::getId, taskId)
                .eq(MsgPushTaskDO::getIsDeleted, 0)
                .one();
        if (task == null) {
            throw new ServiceException("任务不存在");
        }
        task.setSentBy(operator);
        task.setSentTime(LocalDateTime.now());
        this.updateById(task);
        MsgPushTaskItemDO it = mshPushTaskItemService.lambdaQuery()
                .eq(MsgPushTaskItemDO::getTaskId, taskId)
                .eq(MsgPushTaskItemDO::getIsDeleted, 0)
                .eq(MsgPushTaskItemDO::getProcessStatus, MsgProcessStatusEnum.PENDING.getCode())
                .one();
        it.setProcessStatus(MsgProcessStatusEnum.SENT.getCode());
        it.setLastPushTime(LocalDateTime.now());
        mshPushTaskItemService.updateById(it);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelTask(Long taskId, String operator) {
        MsgPushTaskItemDO msgPushTaskItemDO = mshPushTaskItemService.lambdaQuery()
                .eq(MsgPushTaskItemDO::getTaskId, taskId)
                .eq(MsgPushTaskItemDO::getIsDeleted, 0)
                .eq(MsgPushTaskItemDO::getProcessStatus, MsgProcessStatusEnum.PENDING.getCode()).one();
        if (msgPushTaskItemDO == null) {
            throw new ServiceException("任务不存在");
        }
        msgPushTaskItemDO.setProcessStatus(MsgProcessStatusEnum.CANCELLED.getCode());
        mshPushTaskItemService.updateById(msgPushTaskItemDO);
        return true;
    }

    @Override
    public IPage<MsgPushTaskWithDetailsVO> pageTasksWithDetails(MsgPushTaskQueryDTO queryDTO) {
        // 先查询任务分页数据
        IPage<MsgPushTaskDO> taskPage = pageTasks(queryDTO);

        // 创建结果分页对象
        Page<MsgPushTaskWithDetailsVO> resultPage = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        resultPage.setTotal(taskPage.getTotal());
        resultPage.setPages(taskPage.getPages());
        resultPage.setCurrent(taskPage.getCurrent());
        resultPage.setSize(taskPage.getSize());

        if (taskPage.getRecords() == null || taskPage.getRecords().isEmpty()) {
            resultPage.setRecords(Collections.emptyList());
            return resultPage;
        }

        // 获取所有任务ID
        List<Long> taskIds = taskPage.getRecords().stream()
                .map(MsgPushTaskDO::getId)
                .collect(Collectors.toList());

        // 批量查询接收者明细
        List<MsgPushTaskItemDO> allItems = mshPushTaskItemService
                .lambdaQuery()
                .in(MsgPushTaskItemDO::getTaskId, taskIds)
                .eq(MsgPushTaskItemDO::getIsDeleted, 0)
                .list();


        // 按任务ID分组
        Map<Long, List<MsgPushTaskItemDO>> itemsByTaskId = allItems.stream()
                .collect(Collectors.groupingBy(MsgPushTaskItemDO::getTaskId));

        // 构建结果
        List<MsgPushTaskWithDetailsVO> resultList = new ArrayList<>();
        for (MsgPushTaskDO task : taskPage.getRecords()) {
            MsgPushTaskWithDetailsVO vo = new MsgPushTaskWithDetailsVO();
            vo.setTask(task);

            List<MsgPushTaskItemDO> items = itemsByTaskId.getOrDefault(task.getId(), Collections.emptyList());
            vo.setReceivers(items);
            resultList.add(vo);
        }

        resultPage.setRecords(resultList);
        return resultPage;
    }

    @Override
    public MsgPushTaskDetailVO getTaskDetail(Long taskId) {
        MsgPushTaskDO task = this.getById(taskId);
        if (task == null) throw new ServiceException("任务不存在");

        List<MsgPushTaskItemDO> receivers = mshPushTaskItemService
                .lambdaQuery()
                .eq(MsgPushTaskItemDO::getTaskId, taskId)
                .eq(MsgPushTaskItemDO::getIsDeleted, 0)
                .list();

        MsgPushTaskDetailVO vo = new MsgPushTaskDetailVO();
        vo.setTask(task);
        vo.setReceivers(receivers);

        return vo;
    }

    @Override
    public int getUnreadCount(H5MsgUnreadCountDTO unreadCountDTO) {
        if (unreadCountDTO == null || unreadCountDTO.getH5UserId() == null) {
            return 0;
        }
        Long userId = unreadCountDTO.getH5UserId();
        Integer filterType = unreadCountDTO.getType();
        // 先查询符合条件的任务ID（如果指定了消息类型）
        List<Long> filteredTaskIds = null;
        if (filterType != null) {
            List<MsgPushTaskDO> tasks = this.lambdaQuery()
                    .eq(MsgPushTaskDO::getType, filterType)
                    .eq(MsgPushTaskDO::getIsDeleted, 0)
                    .list();
            filteredTaskIds = tasks.stream().map(MsgPushTaskDO::getId).collect(Collectors.toList());
            if (filteredTaskIds.isEmpty()) {
                return 0;
            }
        }

        Long cnt = mshPushTaskItemService.lambdaQuery()
                .eq(MsgPushTaskItemDO::getReceiverId, userId)
                .eq(MsgPushTaskItemDO::getReadStatus, MsgReadStatusEnum.UNREAD.getCode())
                .eq(MsgPushTaskItemDO::getProcessStatus, MsgProcessStatusEnum.SENT.getCode())
                .in(filteredTaskIds != null, MsgPushTaskItemDO::getTaskId, filteredTaskIds)
                .count();
        return cnt == null ? 0 : Math.toIntExact(cnt);
    }

    @Override
    public List<H5MsgListItemVO> getMessageList(H5MsgQueryDTO queryDTO) {

        Long userId = queryDTO.getH5UserId();
        String readStatus = queryDTO.getReadStatus();
        Integer type = queryDTO.getType();
        if (userId == null) {
            return Collections.emptyList();
        }

        Page<MsgPushTaskItemDO> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        IPage<MsgPushTaskItemDO> p = mshPushTaskItemService.lambdaQuery()
                .eq(MsgPushTaskItemDO::getReceiverId, userId)
                .eq(MsgPushTaskItemDO::getProcessStatus, MsgProcessStatusEnum.SENT.getCode()) // 只查询已推送的消息
                .eq(readStatus != null && !readStatus.isEmpty(), MsgPushTaskItemDO::getReadStatus, readStatus)
                .orderByDesc(MsgPushTaskItemDO::getCreateTime)
                .page(page);
        if (p.getRecords() == null) {
            return Collections.emptyList();
        }
        // 获取所有任务ID，用于查询任务详情
        List<Long> taskIds = p.getRecords().stream()
                .map(MsgPushTaskItemDO::getTaskId)
                .distinct()
                .collect(Collectors.toList());

        // 批量查询任务详情
        Map<Long, MsgPushTaskDO> taskMap = new HashMap<>();

        if (!taskIds.isEmpty()) {
            List<MsgPushTaskDO> tasks = this.lambdaQuery()
                    .eq(type != null, MsgPushTaskDO::getType, type)
                    .eq(MsgPushTaskDO::getIsDeleted, 0)
                    .in(MsgPushTaskDO::getId, taskIds).list();

            taskMap = tasks.stream().collect(Collectors.toMap(MsgPushTaskDO::getId, task -> task));
        }

        final Map<Long, MsgPushTaskDO> finalTaskMap = taskMap;
        return p.getRecords().stream().map(it -> {
            H5MsgListItemVO vo = new H5MsgListItemVO();
            vo.setItemId(it.getId());
            vo.setReadStatus(it.getReadStatus());
            vo.setSignStatus(it.getSignStatus());
            vo.setStatus(it.getStatus());
            vo.setProcessStatus(it.getProcessStatus());
            vo.setLastPushTime(it.getLastPushTime());
            MsgPushTaskDO task = finalTaskMap.get(it.getTaskId());
            if (task != null) {
                vo.setTaskId(task.getId());
                vo.setTaskNo(task.getTaskNo());
                vo.setTitle(task.getTitle());
                vo.setContent(task.getContentRendered());
                vo.setType(task.getType());
                vo.setProjectId(task.getProjectId());
                vo.setProjectName(task.getProjectName());
                vo.setNeedSignature(task.getNeedSignature());
                vo.setExpireAt(task.getExpireAt());
                vo.setCreateTime(task.getCreateTime());
                vo.setBusinessNo(task.getBusinessNo());
                vo.setBusinessName(task.getBusinessName());
            }
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public H5MsgDetailVO getMessageItemDetail(Long itemId) {
        if (itemId == null) {
            return null;
        }
        MsgPushTaskItemDO item = mshPushTaskItemService.getById(itemId);
        if (item == null) {
            return null;
        }
        MsgPushTaskDO task = this.getById(item.getTaskId());
        H5MsgDetailVO vo = new H5MsgDetailVO();
        vo.setItemId(item.getId());
        vo.setStatus(item.getProcessStatus());
        vo.setReadStatus(item.getReadStatus());
        if (task != null) {
            vo.setTitle(task.getTitle());
            vo.setContentRendered(task.getContentRendered());
            vo.setContentVars(task.getContentVars());
            vo.setType(task.getType());
            vo.setProjectId(task.getProjectId());
            vo.setProjectName(task.getProjectName());
            vo.setExpireAt(task.getExpireAt());
            vo.setNeedSignature(task.getNeedSignature());
        }
        // 策略分发
        if (task != null && msgDetailEnrichers != null) {
            for (MsgDetailEnricher enricher : msgDetailEnrichers) {
                if (enricher.supports(task.getType())) {
                    enricher.enrich(vo, task);
                }
            }
        }
        return vo;
    }

    @Override
    public boolean markMessageRead(Long itemId) {
        Long userId = SecurityUtils.getUserId();
        MsgPushTaskItemDO it = mshPushTaskItemService.lambdaQuery()
                .eq(MsgPushTaskItemDO::getId, itemId)
                .eq(MsgPushTaskItemDO::getReceiverId, userId)
                .eq(MsgPushTaskItemDO::getProcessStatus, MsgTaskStatusEnum.SENT.getCode())
                .eq(MsgPushTaskItemDO::getIsDeleted, 0)
                .one();
        if (it == null) {
            throw new ServiceException("消息不存在");
        }
        if (Objects.equals(it.getReadStatus(), MsgReadStatusEnum.READ.getCode())) {
            return true;
        }
        it.setReadStatus(MsgReadStatusEnum.READ.getCode());
        it.setReadTime(LocalDateTime.now());
        mshPushTaskItemService.updateById(it);
        saveLog(it.getTaskId(), it.getId(), MsgActionEnum.READ.getCode(), userId, "标记已读");
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean unifiedPush(UnifiedPushDTO pushDTO) {

        if (pushDTO == null || pushDTO.getTemplateId() == null || pushDTO.getProjectId() == null || pushDTO.getMsgType() == null) {
            throw new ServiceException("参数不完整");
        }
        MsgTemplateDO template = templateService.getById(pushDTO.getTemplateId());
        if (template == null || !Objects.equals(template.getStatus(), 1)) {
            throw new ServiceException("模板不可用");
        }

        // 校验消息类型和模板类型的一致性
        if (!Objects.equals(pushDTO.getMsgType(), template.getType())) {
            throw new ServiceException("消息类型与模板类型不匹配，消息类型：" + pushDTO.getMsgType() + "，模板类型：" + template.getType());
        }

        Long taskId = createTask(pushDTO, template);

        return sendNow(taskId, pushDTO.getOperator());
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public H5MsgConfirmVO confirmMessage(H5MsgConfirmDTO confirmDTO) {
//        if (confirmDTO == null || confirmDTO.getH5UserId() == null) {
//            throw new ServiceException("用户ID不能为空");
//        }

        // 1. 获取消息项和任务信息
        MsgPushTaskItemDO item = mshPushTaskItemService.getById(confirmDTO.getItemId());
        if (item == null) throw new ServiceException("消息不存在");
        MsgPushTaskDO task = this.getById(item.getTaskId());
        if (task == null) throw new ServiceException("消息任务不存在");

        // 3. 检查是否需要签署确认（通用逻辑，适用于所有消息类型）
        if (Objects.equals(task.getNeedSignature(), 1)) {
            // 如果消息模板需要签署确认，则所有类型的消息都必须提供签署文件
            if (confirmDTO.getSignFileUrl() == null || confirmDTO.getSignFileUrl().trim().isEmpty()) {
                throw new ServiceException("该消息需要签署确认，请提供签署文件");
            }
            item.setSignStatus(MsgSignStatusEnum.SIGNED.getCode());
            item.setSignFileUrl(confirmDTO.getSignFileUrl());
        } else {
            item.setSignStatus(MsgSignStatusEnum.NOT_REQUIRED.getCode());
        }
        // 更新签署状态
        item.setStatus(1);
        item.setSignTime(LocalDateTime.now());
        mshPushTaskItemService.updateById(item);


        // 4. 使用策略模式处理不同类型的消息确认逻辑（业务特定逻辑）
        if (msgConfirmHandlers != null) {
            for (H5MsgConfirmHandler handler : msgConfirmHandlers) {
                if (handler.supports(task.getType())) {
                    try {
                        handler.handleConfirm(item, task, confirmDTO);
                    } catch (Exception e) {
                        throw new ServiceException("消息确认处理失败: " + e.getMessage());
                    }
                    break; // 找到匹配的处理器后退出
                }
            }
        }
        H5MsgConfirmVO h5MsgConfirmVO = new H5MsgConfirmVO();
        h5MsgConfirmVO.setSignTime(formatter.format(item.getSignTime()));
        h5MsgConfirmVO.setBusinessNo(task.getBusinessNo());
        h5MsgConfirmVO.setBusinessName(task.getBusinessName());
        return h5MsgConfirmVO;
    }

    public IPage<MsgPushTaskDO> pageTasks(MsgPushTaskQueryDTO queryDTO) {
        Page<MsgPushTaskDO> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        return this.lambdaQuery()
                .eq(queryDTO.getType() != null, MsgPushTaskDO::getType, queryDTO.getType())
                .and(queryDTO.getKeyword() != null && !queryDTO.getKeyword().isEmpty(),
                        q -> q.like(MsgPushTaskDO::getTitle, queryDTO.getKeyword())
                                .or().like(MsgPushTaskDO::getProjectName, queryDTO.getKeyword()))
                .orderByDesc(MsgPushTaskDO::getCreateTime).page(page);
    }

    private String genTaskNo() {
        String d = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String seq = String.valueOf((int) (Math.random() * 900000) + 100000);
        return "TS" + d + seq;
    }

    private void saveLog(Long taskId, Long itemId, Integer action, Long operatorId, String detail) {
        MsgActionLogDO log = new MsgActionLogDO();
        log.setTaskId(taskId);
        log.setItemId(itemId);
        log.setAction(action);
        log.setOperatorDomain("");
        log.setOperatorId(operatorId);
        log.setSource("");
        log.setDetail(detail);
        log.setOperateTime(LocalDateTime.now());
        logMapper.insert(log);
    }

    /**
     * 解析JSON变量字符串为Map对象
     * 支持标准JSON格式和简化的键值对格式
     *
     * @param json JSON字符串或键值对字符串
     * @return 解析后的变量Map
     */
    private Map<String, Object> parseJsonVars(String json) {
        try {
            // 空值处理
            if (json == null || json.trim().isEmpty()) {
                return new HashMap<>();
            }

            String trimmedJson = json.trim();

            // 尝试解析为标准JSON格式
            if (trimmedJson.startsWith("{") && trimmedJson.endsWith("}")) {
                @SuppressWarnings("unchecked")
                Map<String, Object> result = JSON.parseObject(trimmedJson, Map.class);
                return result;
            }

            // 尝试解析为键值对格式 (key1=value1&key2=value2)
            if (trimmedJson.contains("=") && (trimmedJson.contains("&") || !trimmedJson.contains("{"))) {
                return parseKeyValuePairs(trimmedJson);
            }

            // 如果都不匹配，返回空Map
            return new HashMap<>();

        } catch (JSONException e) {
            // JSON解析失败，尝试键值对解析
            try {
                return parseKeyValuePairs(json);
            } catch (Exception ex) {
                // 所有解析都失败，返回空Map并记录日志
                log.warn("解析JSON变量失败: {}, 错误: {}", json, ex.getMessage());
                return new HashMap<>();
            }
        } catch (Exception e) {
            // 其他异常，返回空Map并记录日志
            log.warn("解析JSON变量异常: {}, 错误: {}", json, e.getMessage());
            return new HashMap<>();
        }
    }

    /**
     * 解析键值对格式的字符串
     * 支持格式: key1=value1&key2=value2
     *
     * @param keyValueStr 键值对字符串
     * @return 解析后的Map
     */
    private Map<String, Object> parseKeyValuePairs(String keyValueStr) {
        Map<String, Object> result = new HashMap<>();

        if (keyValueStr == null || keyValueStr.trim().isEmpty()) {
            return result;
        }

        // 按&分割键值对
        String[] pairs = keyValueStr.split("&");

        for (String pair : pairs) {
            if (pair == null || pair.trim().isEmpty()) {
                continue;
            }

            // 按=分割键和值
            String[] keyValue = pair.split("=", 2);
            if (keyValue.length == 2) {
                String key = keyValue[0].trim();
                String value = keyValue[1].trim();

                // 尝试解析值为数字或布尔值
                Object parsedValue = parseValue(value);
                result.put(key, parsedValue);
            }
        }

        return result;
    }

    /**
     * 解析字符串值为合适的类型
     *
     * @param value 字符串值
     * @return 解析后的对象
     */
    private Object parseValue(String value) {
        if (value == null || value.isEmpty()) {
            return "";
        }

        // 布尔值
        if ("true".equalsIgnoreCase(value)) {
            return true;
        }
        if ("false".equalsIgnoreCase(value)) {
            return false;
        }

        // 数字
        try {
            // 尝试解析为整数
            if (value.matches("^-?\\d+$")) {
                return Long.parseLong(value);
            }
            // 尝试解析为浮点数
            if (value.matches("^-?\\d+\\.\\d+$")) {
                return Double.parseDouble(value);
            }
        } catch (NumberFormatException e) {
            // 解析失败，返回原字符串
        }

        // 默认返回字符串
        return value;
    }

    private String render(String tpl, Map<String, Object> vars) {
        if (tpl == null) return "";
        String s = tpl;
        if (vars != null) {
            for (Map.Entry<String, Object> e : vars.entrySet()) {
                String key = e.getKey();
                Object val = e.getValue();
                s = s.replace("{" + key + "}", val == null ? "" : String.valueOf(val));
            }
        }
        return s;
    }

    /**
     * 从创建DTO构建任务实体
     */
    private MsgPushTaskDO buildTaskFromCreateDTO(UnifiedPushDTO pushDTO) {
        MsgPushTaskDO task = new MsgPushTaskDO();
        task.setTemplateId(pushDTO.getTemplateId());
        task.setProjectId(pushDTO.getProjectId());
        task.setProjectName(pushDTO.getProjectName());
        task.setBusinessId(pushDTO.getBusinessId());
        task.setRemark(pushDTO.getRemark());

        JSONObject contentVarsJson = new JSONObject();
        contentVarsJson.put("projectName", pushDTO.getProjectName());
        contentVarsJson.put("customerName", pushDTO.getH5UserName());
        task.setContentVars(contentVarsJson.toJSONString());
        return task;
    }

    /**
     * 处理模板校验和内容渲染
     */
    private void processTemplateAndRender(MsgPushTaskDO task, MsgTemplateDO template) {

        // 内容渲染
        Map<String, Object> vars = parseJsonVars(task.getContentVars());
        String rendered = render(template.getContent(), vars);

        // 设置任务属性
        if (task.getId() == null) task.setTaskNo(genTaskNo());
        task.setType(template.getType());
        task.setNeedSignature(template.getNeedSignature());
        task.setContentRendered(rendered);

        // 设置过期时间
        if (template.getExpireDays() != null) {
            int expireDays = Math.max(1, Math.min(30, template.getExpireDays()));
            task.setExpireAt(LocalDateTime.now().plusDays(expireDays));
        }
    }

    public Long createTask(UnifiedPushDTO pushDTO, MsgTemplateDO template) {
        // 构建任务实体
        MsgPushTaskDO task = buildTaskFromCreateDTO(pushDTO);

        task.setTitle(template.getTitle());

        // 处理模板和渲染
        processTemplateAndRender(task, template);

        String businessId = task.getBusinessId();
        if (MsgTypeEnum.DESIGN_DATA.getCode().equals(task.getType())) {
            DesignScheme designScheme = designSchemeService.getById(businessId);
            DesignBase designBase = designBaseService.getById(designScheme.getDesignBaseId());
            task.setBusinessNo(designBase.getDesignNo());
            task.setBusinessName(designScheme.getSchemeName());
        } else if (MsgTypeEnum.MATERIAL_LIST.getCode().equals(task.getType())) {
            PmMaterialList pmMaterialList = pmMaterialListService.getById(businessId);
            task.setBusinessName(pmMaterialList.getListName());
            task.setBusinessNo(pmMaterialList.getProjectNo());
        } else if (MsgTypeEnum.CONTRACT_SIGN.getCode().equals(task.getType())) {
            ContractDTO contract = contractService.getById(Long.valueOf(businessId));
            task.setBusinessNo(contract.getPaperContractNo());
            task.setBusinessName(contract.getContractName());
        } else if (MsgTypeEnum.ACCEPTANCE_INFO.getCode().equals(task.getType())) {
            ConstructionProjectItemDO constructionProjectItemDO = projectItemService.getById(businessId);
            ConstructionProjectDO constructionProjectDO = constructionProjectService.getById(pushDTO.getProjectId());
            task.setBusinessNo(constructionProjectDO.getProjectCode());
            task.setBusinessName(constructionProjectDO.getProjectName() + "-" + constructionProjectItemDO.getItemName());
            projectItemService.lambdaUpdate().set(ConstructionProjectItemDO::getIsPushMsg, 1).eq(ConstructionProjectItemDO::getId, businessId).update();
        } else if (MsgTypeEnum.REQUIREMENT_CHANGE.getCode().equals(task.getType())) {
            DemandChangeRequestDO demandChangeRequestDO = demandChangeRequestService.getById(businessId);
            task.setBusinessNo(demandChangeRequestDO.getChangeNo());
            task.setBusinessName(demandChangeRequestDO.getChangeContent());
        }

        // 保存任务
        task.setCreateTime(LocalDateTime.now());
        this.save(task);

        // 保存接收者
        MsgPushTaskItemDO item = new MsgPushTaskItemDO();

        item.setReceiverId(pushDTO.getH5UserId());
        item.setReceiverName(pushDTO.getH5UserName());
        item.setTaskId(task.getId());
        item.setSignStatus(template.getNeedSignature() == 0 ? 0 : 1);

        mshPushTaskItemService.save(item);

        saveLog(task.getId(), item.getId(), MsgActionEnum.CREATE.getCode(), 1L, "创建任务");

        return task.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long resendMessage(Long originalTaskId, String operator) {
        // 1. 查询原任务信息
        MsgPushTaskDO originalTask = this.lambdaQuery()
                .eq(MsgPushTaskDO::getId, originalTaskId)
                .eq(MsgPushTaskDO::getIsDeleted, 0).one();
        if (originalTask == null) {
            throw new ServiceException("原任务不存在");
        }

        // 2. 查询原任务的接收者信息
        List<MsgPushTaskItemDO> originalItems = mshPushTaskItemService
                .lambdaQuery()
                .eq(MsgPushTaskItemDO::getTaskId, originalTaskId)
                .eq(MsgPushTaskItemDO::getIsDeleted, 0)
                .list();

        if (originalItems.isEmpty()) {
            throw new ServiceException("原任务没有接收者信息");
        }

        // 3. 创建新任务（复制原任务信息）
        MsgPushTaskDO newTask = new MsgPushTaskDO();
        newTask.setTemplateId(originalTask.getTemplateId());
        newTask.setProjectId(originalTask.getProjectId());
        newTask.setProjectName(originalTask.getProjectName());
        newTask.setType(originalTask.getType());
        newTask.setTitle(originalTask.getTitle());
        newTask.setContentRendered(originalTask.getContentRendered());
        newTask.setContentVars(originalTask.getContentVars());
        newTask.setBusinessId(originalTask.getBusinessId());
        newTask.setNeedSignature(originalTask.getNeedSignature());
        newTask.setExpireAt(originalTask.getExpireAt());
        newTask.setRemark("重推消息 - 原任务ID: " + originalTaskId);
        newTask.setTaskNo(genTaskNo());
        newTask.setCreateTime(LocalDateTime.now());
        newTask.setUpdateTime(LocalDateTime.now());

        // 4. 保存新任务
        this.save(newTask);

        // 5. 复制接收者信息
        for (MsgPushTaskItemDO originalItem : originalItems) {
            MsgPushTaskItemDO newItem = new MsgPushTaskItemDO();
            newItem.setTaskId(newTask.getId());
            newItem.setReceiverId(originalItem.getReceiverId());
            newItem.setReceiverName(originalItem.getReceiverName());
            newItem.setReceiverDomain(originalItem.getReceiverDomain());
            newItem.setProcessStatus(MsgProcessStatusEnum.PENDING.getCode());
            newItem.setSignStatus(originalItem.getSignStatus());
            newItem.setCreateTime(LocalDateTime.now());
            newItem.setUpdateTime(LocalDateTime.now());

            mshPushTaskItemService.save(newItem);
        }

        // 6. 立即推送新任务
        sendNow(newTask.getId(), operator);

        return newTask.getId();
    }
}
